// Copyright [2020] <unknown>
#include <bits/stdc++.h>
using namespace std;
// #define ONLINE_JUDGE
#ifndef ONLINE_JUDGE
#define dbg(x...) { cerr << "\033[32;1m" << #x << " -> "; err(x); }
void err() { cerr << "\033[39;0m" << endl; }
template<typename T, typename... A>
void err(T a, A... x) { cerr << a << ' '; err(x...); }
#else
#define dbg(...)
#endif

#define sz(x) ((int)x.size())

typedef long long LL;
const int N = 5e5+50, MOD = 998244353;

LL bin(LL a, LL b, LL p) {
    LL res = 1;
    for (a%=p; b; b>>=1, a=a*a%p)
        res = res * a % p;
    return res;
}

LL fac[N], invf[N];
inline LL C(LL n, LL m) { // n >= m >= 0
    return n < m || m < 0 ? 0 : fac[n] * invf[m] % MOD * invf[n - m] % MOD;
}

inline int bitcnt(int x) {
    int res = 0;
    for (; x; x&=(x-1))
        ++res;
    return res;
}

template<typename T>
struct Bit {
    inline int lowbit(int i) { return i & (-i); }

    T dat[N];

    void clear(int n) {
        memset(dat, 0, sizeof(T) * (n + 1));
    }

    inline void add(int i, T x) {
        for (; i<N; i+=lowbit(i))
            dat[i] += x;
    }

    inline T sum(int i) {
        T res = 0;
        for (; i; i-=lowbit(i))
            res += dat[i];
        return res;
    }
};

Bit<int> bit, bit2;


template<typename T>
struct snode {
    int id;
    T v;
    snode (int id=0, T v=0):id(id), v(v) {}

    bool operator < (const snode &other) const {
        if (v != other.v) return v < other.v;
        else return id < other.id;
    }
};

// template<typename T>
// typedef snode T;
template<typename T>
struct segT {
    T dat[N << 2];
    LL lazy[N << 2];
    int nn;

    void init(int n) {
        nn = 1;
        while (nn < n) 
            nn <<= 1;

        for (int i=1; i<=n; ++i)
            dat[i+nn-1] = snode<int>(i, 0);
        for (int i=nn+n; i<2*nn; ++i)
            dat[i] = snode<int>(-1, 0);
        // for (int i=nn-1; i>=0; --i)
        //     pu(i);
    }

    inline void pd(int rt) {
        if (lazy[rt]) {
            int ls = rt << 1, rs = rt << 1 | 1;
            // dat[ls].v = dat[rs].v = lazy[ls] = lazy[rs] = lazy[rt];
            dat[ls].v |= lazy[rt];
            dat[rs].v |= lazy[rt];
            lazy[ls] |= lazy[rt];
            lazy[rs] |= lazy[rt];
            lazy[rt] = 0;
        }
    }

    inline void pu(int rt) {
        dat[rt].v = dat[rt<<1].v | dat[rt<<1|1].v;
    }

    
    int L, R;

    void u(int l, int r, int rt, int v) {
        if (L <= l && r <= R) {
            dat[rt].v |= v;
            lazy[v] |= v;
            return;
        }
        int m = (l+r) >> 1;
        pd(rt);
        if (L <= m) u(l, m, rt<<1, v);
        if (m+1<=R) u(m+1, r, rt<<1|1, v);
        pu(rt);
    }
    T q(int l, int r, int rt) {
        // dbg(l, r, rt, dat[rt].v);
        if (L <= l && r <= R) {
            return dat[rt];
        }
        int m = (l + r) >> 1; pd(rt);
        T v1 = snode<int>(-1, 0), v2 = snode<int>(-1, 0);
        if (L <= m) v1 = q(l, m, rt<<1);
        if (m+1<=R) v2 = q(m+1, r, rt<<1|1);
        pu(rt);
        return snode(max(v1.id, v2.id), v1.v | v2.v);
    }
    void u(int l, int r, int x) {
        // dbg(l, r, x);
        L = l;
        R = r;
        u(1, nn, 1, x);
    }
    T q(int l, int r) {
        L = l;
        R = r;
        return q(1, nn, 1);
    }
};

segT<snode<int>> seg;

int n, m, k;

struct Q {
    int l, r, v;
    int num, totbitcnt;
} q[N];

int a[N];

vector<int> bucket[N], bq[N];

    vector<int> disc;
inline int getorder(int x) {
    vector<int> &a = disc;
    return lower_bound(a.begin(), a.end(), x) - a.begin();
}

int main(int argc, char const *argv[]) {
    fac[0] = invf[0] = 1;
    for (int i=1; i<N; ++i) {
        fac[i] = fac[i-1] * i % MOD;
    }
    invf[N-1] = bin(fac[N-1], MOD-2, MOD);
    for (int i=N-2; i>=1; --i)
        invf[i] = invf[i+1] * (i+1) % MOD;


    scanf("%d%d%d", &n, &k, &m);
    seg.init(n);

    for (int i=0; i<m; ++i) {
        scanf("%d%d%d", &q[i].l, &q[i].r, &q[i].v);
        seg.u(q[i].l, q[i].r, q[i].v);
        disc.push_back(q[i].v);
        // bucket

    }
    for (int i=1; i<=n; ++i) {
        a[i] = seg.q(i, i).v;
        bit.add(i, bitcnt(a[i]));
        disc.push_back(a[i]);
    }

    sort(disc.begin(), disc.end());
    disc.resize(unique(disc.begin(), disc.end()) - disc.begin());

    for (int i=0; i<m; ++i) {
        bq[getorder(q[i].v)].push_back(i);
        q[i].totbitcnt = bit.sum(q[i].r) - bit.sum(q[i].l-1);
        q[i].totbitcnt = (q[i].r - q[i].l + 1) * k - q[i].totbitcnt;
    }
    for (int i=1; i<=n; ++i) {
        bucket[getorder(a[i])].push_back(i);
    }
    for (int i=0; i<sz(disc); ++i) {
        if (!bq[i].size())
            continue;
        for (int aid : bucket[i])
            bit2.add(aid, 1);

        for (int qid : bq[i])
            q[qid].num = bit2.sum(q[qid].r) - bit2.sum(q[qid].l-1);

        for (int aid : bucket[i])
            bit2.add(aid, -1);
    }
    LL ans = 1;
    for (int i=0; i<m; ++i) {
        if (q[i].num == 0) {
            ans = 0;
            break;
        }

        LL tans = 1;
        int n = q[i].num;
        int totb = q[i].totbitcnt, step = bitcnt(q[i].v);
        totb -= step;
        int num = q[i].num;
        for (int i=1, sgn=1; i<=num; ++i, sgn=-sgn, totb -= step) {
            tans = (tans + sgn * C(n, i) * bin(2, totb, MOD) % MOD) % MOD;
        }

        ans = ans * tans % MOD;
    }
    printf("%lld\n", (ans % MOD + MOD) % MOD);


    // code
    return 0;
}
